package applog

import (
	"errors"
	"fmt"
	"gitee.com/ymofen/gobase"
	"log/slog"
	"runtime"
	"strconv"
	"strings"
)

func GetSource(pc uintptr) *slog.Source {
	fs := runtime.CallersFrames([]uintptr{pc})
	f, _ := fs.Next()
	return &slog.Source{
		Function: f.Function,
		File:     f.File,
		Line:     f.Line,
	}
}

type ReplaceAttrFunc func(groups []string, a slog.Attr) slog.Attr

func NoneReplaceAttr(groups []string, a slog.Attr) slog.Attr {
	return a
}

func GetReplaceAttrOrNull(opt *slog.HandlerOptions) ReplaceAttrFunc {
	if opt != nil && opt.ReplaceAttr != nil {
		return opt.ReplaceAttr
	} else {
		return NoneReplaceAttr
	}
}

func SlogReplaceAttr(groups []string, a slog.Attr) slog.Attr {
	if a.Value.Kind() == slog.KindTime {
		a.Value = slog.StringValue(gobase.DateTimeString(a.Value.Time()))
	} else if a.Key == slog.SourceKey {
		a.Value = slog.StringValue(gobase.ExtractFileName(a.Value.String()))
	}
	return a
}

func ParseSlogLevel(s string) (l slog.Level, err error) {
	defer func() {
		if err != nil {
			err = fmt.Errorf("slog: level string %q: %w", s, err)
		}
	}()

	name := s
	offset := 0
	if i := strings.IndexAny(s, "+-"); i >= 0 {
		name = s[:i]
		offset, err = strconv.Atoi(s[i:])
		if err != nil {
			return 0, err
		}
	}
	switch strings.ToUpper(name) {
	case "DEBUG":
		l = slog.LevelDebug
	case "INFO":
		l = slog.LevelInfo
	case "WARN":
		l = slog.LevelWarn
	case "ERROR":
		l = slog.LevelError
	default:
		return 0, errors.New("unknown name")
	}
	l += slog.Level(offset)
	return
}
